package com.eastmoney.emis.edda.task.eddi;

import com.eastmoney.emis.edda.common.Constants;
import com.eastmoney.emis.edda.domain.entity.EddaApply;
import com.eastmoney.emis.edda.domain.entity.EddiInstruction;
import com.eastmoney.emis.edda.domain.event.EddiInstructionEvent;
import com.eastmoney.emis.edda.domain.event.EventPublisher;
import com.eastmoney.emis.edda.domain.repository.HsbcEddaRepository;
import com.eastmoney.emis.edda.domain.repository.HsbcEddiRepository;
import com.eastmoney.emis.edda.domain.valueobject.EddiOperation;
import com.eastmoney.emis.edda.infrastructure.exception.EddaException;
import com.eastmoney.emis.edda.infrastructure.exception.EddaExceptionStatus;
import com.eastmoney.emis.edda.infrastructure.message.MessageSender;
import com.eastmoney.emis.edda.task.eddi.processor.EddiProcessor;
import com.eastmoney.emis.edda.task.handler.TaskHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.time.LocalDateTime;
import java.util.List;

/**
 * @description: Description
 * @projectName: EDDA-HSBC
 * @package: com.eastmoney.emis.edda.task.eddi
 * @author: 汪程程
 * @date: 2022/10/11 6:19 PM
 * @version: 1.0
 */
@Component("EddiTaskHandler")
public class EddiTaskHandler implements TaskHandler<EddiTask> {
    @Autowired
    private HsbcEddaRepository eddaRepository;
    @Autowired
    private HsbcEddiRepository eddiRepository;
    @Autowired
    private List<EddiProcessor> processors;
    @Autowired
    private MessageSender sender;
    @Autowired
    private EventPublisher eventPublisher;

    @Override
    public void handle(EddiTask task) {
        EddiInstruction eddiInstruction = task.getEddiInstruction();

        if (isInvalidEddiInstruction(eddiInstruction)) {
            eddiInstruction.close();
            eddiRepository.saveDebitInstruction(eddiInstruction);
            publishEddiEvent(task, "无效入金申请");
            return;
        }

        if (ObjectUtils.isEmpty(eddiInstruction.getMandateId())) {
            String ddaApplyEid = eddiInstruction.getNote().replace(Constants.EDDA_NOTE_PREFIX, "");
            EddaApply eddaApply = eddaRepository.findEddaApplyByEid(ddaApplyEid);
            if (eddaApply.fail() || eddaApply.invalid()) {
                eddiInstruction.close();
                eddiRepository.saveDebitInstruction(eddiInstruction);
                publishEddiEvent(task, "eDDA 授权失败");
                return;
            }
            // edda apply 未处理结束
            if (!eddaApply.success()) {
                if (LocalDateTime.now().minusDays(2).isAfter(eddiInstruction.getCreatedTime())) {
                    eddiInstruction.close();
                    eddiRepository.saveDebitInstruction(eddiInstruction);
                    publishEddiEvent(task, "超时关闭");
                }
                return;
            }
            eddiInstruction.setMandateId(eddaApply.getMandateId());
            eddiRepository.updateMandateId(eddiInstruction);
        }

        EddaApply eddaApply = eddaRepository.findActiveEddaApplyByClientIdAndMandateId(eddiInstruction.getClientId(), eddiInstruction.getMandateId());
        if (eddaApply == null) {
            eddiInstruction.close();
            eddiRepository.saveDebitInstruction(eddiInstruction);
            publishEddiEvent(task, EddaExceptionStatus.INVALID_EDDA_BIND.message());
            throw new EddaException(EddaExceptionStatus.INVALID_EDDA_BIND);
        }
        task.setCreditorReference(eddaApply.getCreditReference());
        task.setLanguage(eddaApply.getLanguage());
        eddiInstruction.setProcessTime(LocalDateTime.now());
        eddiInstruction.setProcessUserName(task.getProcessUserName());
        eddiInstruction.setProcessUid(task.getProcessUid());

        for (EddiProcessor processor : processors) {
            processor.process(task);
        }

        sender.send(task.getEddiInstruction(), eddaApply.hasEddi());
    }

    private void publishEddiEvent(EddiTask task, String errorReason) {
        EddiInstructionEvent event = new EddiInstructionEvent(task.getEddiInstruction());
        event.setOperation(EddiOperation.APPLY.getValue());
        event.setProcessUid(task.getProcessUid());
        event.setProcessUserName(task.getProcessUserName());
        event.setErrorReason(errorReason);
        eventPublisher.publish(event);
    }

    private boolean isInvalidEddiInstruction(EddiInstruction eddiInstruction) {
        String note = eddiInstruction.getNote();
        return ObjectUtils.isEmpty(eddiInstruction.getMandateId()) &&
                (ObjectUtils.isEmpty(note) || !note.startsWith(Constants.EDDA_NOTE_PREFIX));
    }

}
